using System;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.IO;
using System.IO.Compression;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
using System.Timers;
using System.Web;
using System.Web.Mail;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;

namespace Halide
{
	/// <summary>
	/// The Http class contains methods and properties for performing or evaluating HTTP operations.
	/// This includes cookies, domain redirection, and more.
	/// </summary>
	sealed public class Http
	{
		private static string _version = "2007.12.25A";

		/// <summary>
		/// Return the version number of the class; read-only.
		/// </summary>
		/// <value>
		/// A string with the version number of the class.
		/// </value>
		public static string Version
		{
			get
			{
				return _version;
			}
		}

		/// <summary>
		/// No constructor is necessary.
		/// </summary>
		private Http()
	    {
	    }

	    /// <summary>
	    /// Returns a specified cookie from a specified request object.
	    /// </summary>
		/// <example>
		/// <code>
		/// string cookieVal = Halide.Http.GetCookie(Request, "Score");
		/// </code>
		/// </example>
	    /// <param name="Request">HttpRequest object.</param>
	    /// <param name="cookieName">Name of cookie to retrieve.</param>
		/// <returns>A cookie value.</returns>
	    public static string GetCookie(System.Web.HttpRequest Request, string cookieName)
	    {
	        if (Request.Cookies[cookieName] != null) return Request.Cookies[cookieName].Value.ToString();
	        return (string.Empty);
	    }

		/// <summary>
		/// Returns a specified cookie from the current request object.
		/// </summary>
		/// <example>
		/// <code>
		/// string cookieVal = Halide.Http.GetCookie("Score");
		/// </code>
		/// </example>
		/// <param name="cookieName">Name of cookie to retrieve.</param>
		/// <returns>A cookie value.</returns>
		public static string GetCookie(string cookieName)
	    {
	        return GetCookie(HttpContext.Current.Request, cookieName);
	    }

	    /// <summary>
	    /// Create a cookie on the client web browser.
	    /// </summary>
		/// <example>
		/// <code>
		/// Halide.Http.SetCookie("Score", "15", "/", 7);
		/// </code>
		/// </example>
	    /// <param name="cookieName">Name of the cookie to create.</param>
	    /// <param name="cookieValue">Cookie string value.</param>
	    /// <param name="path">Virtual web path for cookie ownership (eg. use "/" for the root web site).</param>
	    /// <param name="days">Number of days until expiration.</param>
		/// <returns>Nothing.</returns>
	    public static void SetCookie(string cookieName, string cookieValue, string path, int days)
	    {
			HttpContext.Current.Response.Cookies[cookieName].Value = cookieValue;
			HttpContext.Current.Response.Cookies[cookieName].Expires = DateTime.Now.AddDays(days);
			if(!String.IsNullOrEmpty(path)) HttpContext.Current.Response.Cookies[cookieName].Path = path;
	    }

	    /// <summary>
	    /// Determine if the user needs to be redirected to a new URL,
		/// for sites that have multiple domain names, but one primary
		/// (eg. like catching misspellings in domain names). The transport
		/// (eg. http://) is not used or returned with the result of the method.
	    /// </summary>
		/// <example>
		/// <code>
		/// string newURL = Halide.Http.DomainRedirect("default.aspx", "pocketkaos.com");
		///
		/// if (!String.IsNullOrEmpty(newURL))
		///		Response.Redirect("http://" + newURL);
		/// </code>
		/// </example>
	    /// <param name="defaultPageName">default page file name used on the site (eg. default.aspx).</param>
	    /// <param name="domainName">Primary domain name that should be used (eg. www.pocketkaos.com).</param>
		/// <returns>A new URL for redirection (without transport, but with any parameters), or an empty string if the user is using the correct (primary) domain name.</returns>
	    public static string DomainRedirect(string defaultPageName, string domainName)
	    {
			string pageName = defaultPageName.ToLower();
			string domain = domainName.ToLower();

			string SERVER = HttpContext.Current.Request.ServerVariables["SERVER_NAME"].ToString().ToLower();
			string URL = HttpContext.Current.Request.ServerVariables["SCRIPT_NAME"].ToString().ToLower().Replace("/" + pageName, "/");

			if(HttpContext.Current.Request.ServerVariables["QUERY_STRING"].ToString().Length > 0) URL += "?" + HttpContext.Current.Request.ServerVariables["QUERY_STRING"].ToString();

			if(SERVER.IndexOf(domain) == -1)
			{
				return (domain + URL);
			}
			else
			{
				return (String.Empty);	
			}
	    }

		/// <summary>
		/// Enumeration used with the GetWebPage method.
		/// </summary>
        public enum GetWebPageMethod
		{
			/// <summary>
			/// Http GET operation.
			/// </summary>
			Get,

			/// <summary>
			/// Http POST operation.
			/// </summary>
			Post
		};
 
	    /// <summary>
	    /// Perform an Http GET operation, and return the result.
	    /// </summary>
		/// <example>
		/// <code>
		/// string retVal = Halide.Http.GetWebPage("http://www.site.com");
		/// </code>
		/// </example>
	    /// <param name="url">Fully qualified URL to the remote page.</param>
		/// <returns>A string with the result from the GET operation.</returns> 
        public static string GetWebPage(string url)
        {
            return GetWebPage(url, GetWebPageMethod.Get, null, null, null, null);
        }
 
	    /// <summary>
	    /// Perform an Http GET operation, passing cookies, and return the result.
	    /// </summary>
		/// <example>
		/// <code>
		/// string retVal = Halide.Http.GetWebPage("http://www.site.com", myCookies);
		/// </code>
		/// </example>
		/// <param name="url">Fully qualified URL to the remote page.</param>
	    /// <param name="cookies">CookieContainer variable for sending cookies.</param>
		/// <returns>A string with the result from the GET operation.</returns> 
        public static string GetWebPage(string url, CookieContainer cookies)
        {
            return GetWebPage(url, GetWebPageMethod.Get, cookies, null, null, null);
        }
 
	    /// <summary>
	    /// Perform an Http GET or POST operation, and return the result.
	    /// </summary>
		/// <example>
		/// <code>
		/// string retVal = Halide.Http.GetWebPage("http://www.site.com", Halide.Http.GetWebPageMethod.Get, postData);
		/// </code>
		/// </example>
	    /// <param name="url">Fully qualified URL to the remote page.</param>
	    /// <param name="method">GetWebPageMethod enum value.</param>
	    /// <param name="postData">String post data for sending a post.</param>
		/// <returns>A string with the result from the GET or POST operation.</returns> 
        public static string GetWebPage(string url, GetWebPageMethod method, string postData)
        {
            return GetWebPage(url, method, null, postData, null, null);
        }
 
	    /// <summary>
	    /// Perform an Http GET operation, passing credentials, and return the result.
	    /// </summary>
		/// <example>
		/// <code>
		/// string retVal = Halide.Http.GetWebPage("http://www.site.com", "jsmith", "password");
		/// </code>
		/// </example>
		/// <param name="url">Fully qualified URL to the remote page.</param>
	    /// <param name="userName">User name string for Windows Authentication.</param>
	    /// <param name="password">Password string for Windows Authentication.</param>
		/// <returns>A string with the result from the GET operation.</returns> 
        public static string GetWebPage(string url, string userName, string password)
        {
            return GetWebPage(url, GetWebPageMethod.Get, null, null, userName, password);
        }
 
	    /// <summary>
	    /// Perform an Http GET or POST operation, passing cookies, post data,
		/// user name and password, and return the result.
	    /// </summary>
		/// <example>
		/// <code>
		/// string retVal = Halide.Http.GetWebPage("http://www.site.com", Halide.Http.GetWebPageMethod.Get, cookies, postData, "jsmith", "password");
		/// </code>
		/// </example>
		/// <param name="url">Fully qualified URL to the remote page.</param>
	    /// <param name="method">GetWebPageMethod enum value.</param>
	    /// <param name="cookies">CookieContainer variable for sending cookies.</param>
	    /// <param name="postData">String post data for sending a post.</param>
	    /// <param name="userName">User name string for Windows Authentication.</param>
	    /// <param name="password">Password string for Windows Authentication.</param>
		/// <returns>A string with the result from the GET or POST operation.</returns> 
		public static string GetWebPage(string url, GetWebPageMethod method, CookieContainer cookies, string postData, string userName, string password)
		{
			try
			{       
				string response;

				HttpWebRequest objRequest = (HttpWebRequest)WebRequest.Create(url);

				if (!String.IsNullOrEmpty(userName) || !String.IsNullOrEmpty(password))
				{
					NetworkCredential nc = new NetworkCredential();
					nc.UserName = userName;
					nc.Password = password;
					objRequest.Credentials = nc;
				}

				objRequest.AllowWriteStreamBuffering = true;
				objRequest.Method = method.ToString().ToUpper();

				if(cookies!=null) objRequest.CookieContainer = cookies;

				objRequest.AllowAutoRedirect = true;
				objRequest.Timeout = 30000;
				objRequest.Proxy = null;
				objRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)";

				if (method == GetWebPageMethod.Post && !String.IsNullOrEmpty(postData))
				{
					objRequest.ContentType = "application/x-www-form-urlencoded";
					using (StreamWriter myWriter = new StreamWriter(objRequest.GetRequestStream()))
					myWriter.Write(postData);
				}

				HttpWebResponse objResponse = (HttpWebResponse)objRequest.GetResponse();

				//if redirected, this is the final uri
				//FinalURL = objResponse.ResponseUri.ToString();

				using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
				response = sr.ReadToEnd();

				return response;
			}
			catch
			{
				return "";
			}
		}

		/// <summary>
		/// Retrieve the current page file name.
		/// </summary>
		/// <returns>Current page file name as a string.</returns>
		public static string GetCurrentPageName()
		{ 
			string sPath = System.Web.HttpContext.Current.Request.Url.AbsolutePath;
			System.IO.FileInfo oInfo = new System.IO.FileInfo(sPath); 
			string sRet = oInfo.Name; 
			
			return sRet; 
		} 

	// Outer Identify class
	}


	/// <summary>
	/// Simple method to submit post data to a url.
	/// </summary>
	/// <example>
	/// <code>
	/// Halide.HttpPost post = new Halide.HttpPost();
	/// post.Url="http://seeker.dice.com/jobsearch/servlet/JobSearch";
	/// post.PostItems.Add("op","100");
	/// post.PostItems.Add("rel_code","1102");
	/// post.PostItems.Add("FREE_TEXT","c# jobs");
	/// post.PostItems.Add("SEARCH","");
	/// post.Type = Halide.HttpPost.PostTypeEnum.Post;
	/// string result = post.Post();
	/// </code>
	/// </example>
	public class HttpPost
	{
		/// <summary>
		/// determines what type of post to perform.
		/// </summary>
		public enum PostTypeEnum
		{
			/// <summary>
			/// Does a get against the source.
			/// </summary>
			Get,
			/// <summary>
			/// Does a post against the source.
			/// </summary>
			Post
		}

		private string m_url=string.Empty;
		private NameValueCollection m_values=new NameValueCollection();
		private PostTypeEnum m_type=PostTypeEnum.Get;
		/// <summary>
		/// Default constructor.
		/// </summary>
		public HttpPost()
		{
		}

		/// <summary>
		/// Constructor that accepts a url as a parameter
		/// </summary>
		/// <param name="url">The url where the post will be submitted to.</param>
		public HttpPost(string url):this()
		{
			m_url=url;
		}

		/// <summary>
		/// Constructor allowing the setting of the url and items to post.
		/// </summary>
		/// <param name="url">the url for the post.</param>
		/// <param name="values">The values for the post.</param>
		public HttpPost(string url, NameValueCollection values):this(url)
		{
			m_values=values;
		}

		/// <summary>
		/// Gets or sets the url to submit the post to.
		/// </summary>
		public string Url
		{
			get
			{
				return m_url;
			}
			set
			{
				m_url=value;
			}
		}
		/// <summary>
		/// Gets or sets the name value collection of items to post.
		/// </summary>
		public NameValueCollection PostItems
		{
			get
			{
				return m_values;
			}
			set
			{
				m_values = value;
			}
		}
		/// <summary>
		/// Gets or sets the type of action to perform against the url.
		/// </summary>
		public PostTypeEnum Type
		{
			get
			{
				return m_type;
			}
			set
			{
				m_type=value;
			}
		}
		/// <summary>
		/// Posts the supplied data to specified url.
		/// </summary>
		/// <returns>a string containing the result of the post.</returns>
		public string Post()
		{
			StringBuilder parameters=new StringBuilder();

			for (int i=0;i < m_values.Count;i++)
			{
				EncodeAndAddItem(ref parameters,m_values.GetKey(i),m_values[i]);
			}

			string result = PostData(m_url,parameters.ToString());
			
			return result;
		}
		/// <summary>
		/// Posts the supplied data to specified url.
		/// </summary>
		/// <param name="url">The url to post to.</param>
		/// <returns>a string containing the result of the post.</returns>
		public string Post(string url)
		{
			m_url=url;
			return this.Post();
		}
		/// <summary>
		/// Posts the supplied data to specified url.
		/// </summary>
		/// <param name="url">The url to post to.</param>
		/// <param name="values">The values to post.</param>
		/// <returns>a string containing the result of the post.</returns>
		public string Post(string url, NameValueCollection values)
		{
			m_values=values;
			return this.Post(url);
		}
		/// <summary>
		/// Posts data to a specified url. Note that this assumes that you have already url encoded the post data.
		/// </summary>
		/// <param name="postData">The data to post.</param>
		/// <param name="url">the url to post to.</param>
		/// <returns>Returns the result of the post.</returns>
		private string PostData(string url, string postData)
		{
			HttpWebRequest request=null;
			if (m_type==PostTypeEnum.Post)
			{
				Uri uri = new Uri(url);
				request = (HttpWebRequest) WebRequest.Create(uri);
				request.Method = "POST";
				request.ContentType = "application/x-www-form-urlencoded";
				request.ContentLength = postData.Length;
				using(Stream writeStream = request.GetRequestStream())
				{
					UTF8Encoding encoding = new UTF8Encoding();
					byte[] bytes = encoding.GetBytes(postData);
					writeStream.Write(bytes, 0, bytes.Length);
				}
			}
			else
			{
				Uri uri = new Uri(url + "?" + postData);
				request = (HttpWebRequest) WebRequest.Create(uri);
				request.Method = "GET";
			}
			string result=string.Empty;
			using (HttpWebResponse response = (HttpWebResponse) request.GetResponse())
			{
				using (Stream responseStream = response.GetResponseStream())
				{
					using (StreamReader readStream = new StreamReader (responseStream, Encoding.UTF8))
					{
						result = readStream.ReadToEnd();
					}
				}
			}
			return result;
		}
		/// <summary>
		/// Encodes an item and ads it to the string.
		/// </summary>
		/// <param name="baseRequest">The previously encoded data.</param>
		/// <param name="key">The key value to assign the encoded dataItem.</param>
		/// <param name="dataItem">The data to encode.</param>
		/// <returns>A string containing the old data and the previously encoded data.</returns>
		private static void EncodeAndAddItem(ref StringBuilder baseRequest, string key, string dataItem)
		{
			if (baseRequest == null)
			{
				baseRequest = new StringBuilder();
			}

			if (baseRequest.Length != 0)
			{
				baseRequest.Append("&");
			}

			baseRequest.Append(key);
			baseRequest.Append("=");
			baseRequest.Append(System.Web.HttpUtility.UrlEncode(dataItem));
		}
	}

// Outer namespace
}